import { Request, Response, NextFunction } from 'express';
import settingsService from '@services/settings.service';
import logger from '@utils/logger';
import { SettingsType } from '@database/models/Settings';

/**
 * Settings Controller
 */
class SettingsController {
  /**
   * Get user settings
   */
  async getUserSettings(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const userId = req.user?._id.toString() || req.params.userId;

      if (!userId) {
        res.status(401).json({
          success: false,
          message: 'User not authenticated'
        });
        return;
      }

      const settings = await settingsService.getUserSettings(userId);

      res.status(200).json({
        success: true,
        data: settings
      });
    } catch (error) {
      logger.error('Failed to get user settings:', error as Error);
      next(error);
    }
  }

  /**
   * Get user preferences
   */
  async getUserPreferences(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const userId = req.user?._id.toString() || req.params.userId;

      if (!userId) {
        res.status(401).json({
          success: false,
          message: 'User not authenticated'
        });
        return;
      }

      const preferences = await settingsService.getUserPreferences(userId);

      res.status(200).json({
        success: true,
        data: preferences
      });
    } catch (error) {
      logger.error('Failed to get user preferences:', error as Error);
      next(error);
    }
  }

  /**
   * Update user preferences
   */
  async updateUserPreferences(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const userId = req.user?._id.toString();
      const updatedBy = req.user?.email || userId;

      if (!userId) {
        res.status(401).json({
          success: false,
          message: 'User not authenticated'
        });
        return;
      }

      const preferences = req.body;
      const result = await settingsService.updateUserPreferences(userId, preferences, updatedBy);

      res.status(200).json({
        success: true,
        data: result,
        message: 'User preferences updated successfully'
      });
    } catch (error) {
      logger.error('Failed to update user preferences:', error as Error);
      next(error);
    }
  }

  /**
   * Update user setting
   */
  async updateUserSetting(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const userId = req.user?._id.toString();
      const updatedBy = req.user?.email || userId;
      const { key, value } = req.body;

      if (!userId) {
        res.status(401).json({
          success: false,
          message: 'User not authenticated'
        });
        return;
      }

      if (!key || value === undefined) {
        res.status(400).json({
          success: false,
          message: 'Key and value are required'
        });
        return;
      }

      const result = await settingsService.updateUserSettings(userId, key, value, updatedBy);

      res.status(200).json({
        success: true,
        data: result,
        message: 'Setting updated successfully'
      });
    } catch (error) {
      logger.error('Failed to update user setting:', error as Error);
      next(error);
    }
  }

  /**
   * Get system settings
   */
  async getSystemSettings(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const settings = await settingsService.getSystemSettings();

      res.status(200).json({
        success: true,
        data: settings
      });
    } catch (error) {
      logger.error('Failed to get system settings:', error as Error);
      next(error);
    }
  }

  /**
   * Get system config
   */
  async getSystemConfig(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const config = await settingsService.getSystemConfig();

      res.status(200).json({
        success: true,
        data: config
      });
    } catch (error) {
      logger.error('Failed to get system config:', error as Error);
      next(error);
    }
  }

  /**
   * Update system config
   */
  async updateSystemConfig(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const updatedBy = req.user?.email || req.user?._id.toString() || 'admin';
      const config = req.body;

      const result = await settingsService.updateSystemConfig(config, updatedBy);

      res.status(200).json({
        success: true,
        data: result,
        message: 'System config updated successfully'
      });
    } catch (error) {
      logger.error('Failed to update system config:', error as Error);
      next(error);
    }
  }

  /**
   * Update system setting
   */
  async updateSystemSetting(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const updatedBy = req.user?.email || req.user?._id.toString() || 'admin';
      const { key, value } = req.body;

      if (!key || value === undefined) {
        res.status(400).json({
          success: false,
          message: 'Key and value are required'
        });
        return;
      }

      const result = await settingsService.updateSystemSettings(key, value, updatedBy);

      res.status(200).json({
        success: true,
        data: result,
        message: 'System setting updated successfully'
      });
    } catch (error) {
      logger.error('Failed to update system setting:', error as Error);
      next(error);
    }
  }

  /**
   * Get integration settings
   */
  async getIntegrationSettings(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const settings = await settingsService.getIntegrationSettings();

      res.status(200).json({
        success: true,
        data: settings
      });
    } catch (error) {
      logger.error('Failed to get integration settings:', error as Error);
      next(error);
    }
  }

  /**
   * Get integration config
   */
  async getIntegrationConfig(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const config = await settingsService.getIntegrationConfig();

      res.status(200).json({
        success: true,
        data: config
      });
    } catch (error) {
      logger.error('Failed to get integration config:', error as Error);
      next(error);
    }
  }

  /**
   * Update integration setting
   */
  async updateIntegrationSetting(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const updatedBy = req.user?.email || req.user?._id.toString() || 'admin';
      const { key, value } = req.body;

      if (!key || value === undefined) {
        res.status(400).json({
          success: false,
          message: 'Key and value are required'
        });
        return;
      }

      const result = await settingsService.updateIntegrationSettings(key, value, updatedBy);

      res.status(200).json({
        success: true,
        data: result,
        message: 'Integration setting updated successfully'
      });
    } catch (error) {
      logger.error('Failed to update integration setting:', error as Error);
      next(error);
    }
  }

  /**
   * Get notification channels
   */
  async getNotificationChannels(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const channels = await settingsService.getNotificationChannels();

      res.status(200).json({
        success: true,
        data: channels
      });
    } catch (error) {
      logger.error('Failed to get notification channels:', error as Error);
      next(error);
    }
  }

  /**
   * Update notification channels
   */
  async updateNotificationChannels(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const updatedBy = req.user?.email || req.user?._id.toString() || 'admin';
      const channels = req.body;

      if (!Array.isArray(channels)) {
        res.status(400).json({
          success: false,
          message: 'Channels must be an array'
        });
        return;
      }

      const result = await settingsService.updateNotificationChannels(channels, updatedBy);

      res.status(200).json({
        success: true,
        data: result,
        message: 'Notification channels updated successfully'
      });
    } catch (error) {
      logger.error('Failed to update notification channels:', error as Error);
      next(error);
    }
  }

  /**
   * Reset user settings to defaults
   */
  async resetUserSettings(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const userId = req.user?._id.toString();

      if (!userId) {
        res.status(401).json({
          success: false,
          message: 'User not authenticated'
        });
        return;
      }

      const result = await settingsService.resetToDefaults(SettingsType.USER, userId);

      res.status(200).json({
        success: true,
        data: { deleted: result },
        message: 'User settings reset to defaults'
      });
    } catch (error) {
      logger.error('Failed to reset user settings:', error as Error);
      next(error);
    }
  }

  /**
   * Reset system settings to defaults
   */
  async resetSystemSettings(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const result = await settingsService.resetToDefaults(SettingsType.SYSTEM);

      res.status(200).json({
        success: true,
        data: { deleted: result },
        message: 'System settings reset to defaults'
      });
    } catch (error) {
      logger.error('Failed to reset system settings:', error as Error);
      next(error);
    }
  }
}

export default new SettingsController();
